package com.tarena.csmall.seckill.rpc;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.pojo.seckill.dto.SeckillStockDTO;
import cn.tedu.mall.pojo.seckill.model.SeckillStockLog;
import com.tarena.csmall.seckill.api.SeckillStockApi;
import com.tarena.csmall.seckill.mapper.SeckillSkuMapper;
import com.tarena.csmall.seckill.mapper.SeckillStockLogMapper;
import java.time.LocalDateTime;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

@DubboService
@Slf4j
public class SeckillStockRpcImpl implements SeckillStockApi {
    @Autowired
    private SeckillSkuMapper seckillSkuMapper;
    @Autowired
    private SeckillStockLogMapper seckillStockLogMapper;
    @Override public void reduceSeckillStock(SeckillStockDTO dto) {
        //将这个方法,设计成幂等逻辑
        //因为每次减库存,都会记录减库存日志,日志数据包含每张订单的sn编号,一张订单唯一sn,只允许减一次
        int count=seckillStockLogMapper.selectCountByOrderSn(dto.getSn());
        if(count>0){
            log.info("订单已经减过库存了,sn:{}",dto.getSn());
            return;
        }
        log.info("减库存:{}",dto);
        //update seckill_sku set stock=stock-#{quantity} where id=#{skuId} and stock>=#{quantity}
        int result=seckillSkuMapper.reduceStock(dto);
        if(result==0){
            throw new CoolSharkServiceException(ResponseCode.BAD_REQUEST,"减库存失败");
        }
        //记录一下哪张订单的哪个sku 减了多少个库存
        SeckillStockLog stockLog=new SeckillStockLog();
        stockLog.setOrderSn(dto.getSn());
        stockLog.setSkuId(dto.getSkuId());
        stockLog.setQuantity(dto.getQuantity());
        LocalDateTime now=LocalDateTime.now();
        stockLog.setGmtCreate(now);
        stockLog.setGmtModified(now);
        seckillStockLogMapper.insert(stockLog);
    }

    /**
     * 1. seckill_stock_log日志中存在才能回退,使用sn+skuId 查询日志数据
     * 2. 如果日志不存在,不需要回退 如果日志存在,需要回退的
     * 3. 根据日志查询结果,对应的sku商品库存 回退quantity个
     * 4. 记录的日志删除
     */
    @Override public void returnSeckillStock(SeckillStockDTO dto) {
        int count = seckillStockLogMapper.selectCountByOrderSn(dto.getSn());
        if (count > 0 ){
            //需要查询日志 回退库存数据
            SeckillStockLog stockLog=seckillStockLogMapper.selectStockLog(dto.getSn(),dto.getSkuId());
            //使用quantity update seckill_sku set stock=stock+#{quantity} where id=#{skuId}
            seckillSkuMapper.incrementStock(stockLog);
            //删除日志 delete from seckill_stock_log where id=id
            seckillStockLogMapper.deleteByPrimaryKey(stockLog.getId());
        }
    }
}
